/******************************************************************************

	COPYRIGHT(C) JONAS 'SORTIE' TERMANSEN 2010.

	This file is part of the Maxsi Library.

	Maxsi Library is free software: you can redistribute it and/or modify it
	under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 of the License, or (at your
	option) any later version.

	Maxsi Library is distributed in the hope that it will be useful, but
	WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
	or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
	License for more details.

	You should have received a copy of the GNU Lesser General Public License
	along with Maxsi Library. If not, see <http://www.gnu.org/licenses/>.

	Maxsi Library
	A powerful Cross-Platform C++ General Purpose Library that allows you to
	efficiently create high-performance and reliable applications.

	MaxsiInterface.h
	A system that allows you to easily create different implementations of the
	same virtual base class. It makes the Maxsi Library ridiculously modular.

******************************************************************************/

#ifndef MaxsiInterface_H
#define MaxsiInterface_H

BeginMaxsiNamespace

#define MAXSI_INTERFACE_DYNAMIC		(0)
#define MAXSI_INTERFACE_STATIC		(1<<0)

MAXSI_CLASSLINK MaxsiInterface
{
public:
	MaxsiInterface();
	virtual ~MaxsiInterface();

public:
	virtual const char* GetImplementationName() = 0;
	virtual size_t Implements(char** List, size_t ListSize);
	virtual const FLAGSL32 GetInterfaceFeatures() = 0;
	
};

typedef MaxsiInterface* (*MaxsiImplementationFactor)(void);
typedef void (*MaxsiImplementationDestructory)(MaxsiInterface*);

MAXSI_LINK MaxsiError AddImplementation(MaxsiImplementationFactor Factory, MaxsiImplementationDestructory Destructory);
MAXSI_LINK MaxsiError RemoveImplementation(char* ClassName);

MAXSI_LINK MaxsiInterface* GetStaticClass(char* InterfaceName);
MAXSI_LINK MaxsiInterface* CreateInterface(char* InterfaceName);
MAXSI_LINK void DeleteInterface(MaxsiInterface* Instance);

#define MAXSI_DECLARE_INTERFACE(Class)

#define MAXSI_DECLARE_IMPLEMENTATION(Class, Interface, Parameters) \
	MAXSI_DECLARE_CHILD_CLASS(Class, Interface) \
public: \
	virtual const char* GetImplementationName(); \
	virtual size_t Implements(char** List, size_t ListSize); \
	virtual const FLAGSL32 GetInterfaceFeatures();

#define MAXSI_DECLARE_SELF_IMPLEMENTATION(Class, Parameters) \
	MAXSI_DECLARE_IMPLEMENTATION(Class, Class, Parameters)

#define MAXSI_DEFINE_IMPLEMENTATION(Class, Interface, Parameters) \
	const char* Class::GetImplementationName() \
	{ \
		return #Class; \
	} \
	\
	size_t Class::Implements(char** List, size_t ListSize) \
	{ \
		if ( List == NULL || ListSize == 0 ) { return 1 + BaseClass::Implements(List, ListSize); } \
		\
		size_t Location = BaseClass::Implements(List, ListSize); \
		\
		if ( Location < ListSize ) { List[Location] = #Interface; } \
		\
		return Location + 1; \
	} \
	\
	const FLAGSL32 Class::GetInterfaceFeatures() { return Parameters; }\
	\
	MaxsiInterface* Class##Factory() { return new Class; } \
	void Class##Destructory(MaxsiInterface* Instance) { delete (Class*)Instance; } \
	\
	class Class##Auto \
	{ \
	public: \
		Class##Auto() { AddImplementation(Class##Factory, Class##Destructory); } \
		~Class##Auto() { RemoveImplementation(#Class); } \
	}; \
	\
	Class##Auto Class##AutoInstance;


#define MAXSI_DEFINE_SELF_IMPLEMENTATION(Class, Parameters) \
	const char* Class::GetImplementationName() \
	{ \
		return #Class; \
	} \
	\
	size_t Class::Implements(char** List, size_t ListSize) \
	{ \
		if ( List == NULL || ListSize == 0 ) { return 1;  } \
		\
		size_t Location = 0; \
		\
		if ( Location < ListSize ) { List[Location] = #Class; } \
		\
		return Location + 1; \
	} \
	\
	const FLAGSL32 Class::GetInterfaceFeatures() { return Parameters; }\
	\
	MaxsiInterface* Class##Factory() { return new Class; } \
	void Class##Destructory(MaxsiInterface* Instance) { delete (Class*)Instance; } \
	\
	class Class##Auto \
	{ \
	public: \
		Class##Auto() { AddImplementation(Class##Factory, Class##Destructory); } \
		~Class##Auto() { RemoveImplementation(#Class); } \
	}; \
	\
	Class##Auto Class##AutoInstance;

//=============================================================================
//	Interface macros, used to declare classes that are defined elsewhere, or
//	abstract baseclasses, such as the Maxsi Window System. The meaning of the
//	MAXSI_INTERFACE suffix on functions is not defined here and must be
//	#undef'd before and re-#define'd before the class is declared. Afterwards
//	it must be #undef'd and #define'd to emptiness. When #define'd before a
//	class declaration it must be defined to a below macro depending on whether
//	the class is implemented in this library. This allows us to copy-paste the
//	actual class declaration between header files or child classes.
//=============================================================================
// You can use the following macros:
// MAXSI_INTERFACE_VIRTUAL_FUNCTION - This function is not implemented in this binary.
// MAXSI_INTERFACE_IMPLEMENTED_FUNCTION - This function is implemented in this binary.
// MAXSI_INTERFACE_ABSTRACT_BASECLASS - This function is not implemented anywhere because the class is abstract.
// MAXSI_INTERFACE_IMPLEMENTED_IN_MAXSI_LIBRARY - This function is implemented in Maxsi Library.
// MAXSI_INTERFACE_IMPLEMENTED_ELSEWHERE - This function is defined in your application.

#define MAXSI_INTERFACE_VIRTUAL_FUNCTION = 0
#define MAXSI_INTERFACE_IMPLEMENTED_FUNCTION
#define MAXSI_INTERFACE_ABSTRACT_BASECLASS MAXSI_INTERFACE_VIRTUAL_FUNCTION
#define MAXSI_INTERFACE_RESET_IT_TO_THIS You_Forgot_To_ReDefine_MAXSI_INTERFACE
#define MAXSI_INTERFACE MAXSI_INTERFACE_RESET_IT_TO_THIS

//=============================================================================
//	Declare macros for interfaces in the Maxsi Library or not.
//=============================================================================
#ifdef Maxsi_Library_Implementation
#define MAXSI_INTERFACE_IMPLEMENTED_IN_MAXSI_LIBRARY MAXSI_INTERFACE_IMPLEMENTED_FUNCTION
#define MAXSI_INTERFACE_IMPLEMENTED_ELSEWHERE MAXSI_INTERFACE_VIRTUAL_FUNCTION
#else
#define MAXSI_INTERFACE_IMPLEMENTED_IN_MAXSI_LIBRARY MAXSI_INTERFACE_IMPLEMENTED_FUNCTION
#define MAXSI_INTERFACE_IMPLEMENTED_ELSEWHERE MAXSI_INTERFACE_IMPLEMENTED_FUNCTION
#endif

EndMaxsiNamespace

#endif

